package il.ac.tau.arielgue.outxing.helpers;

import il.ac.tau.arielgue.outxing.agents.FAOOrganism;
import il.ac.tau.arielgue.outxing.agents.OutXingOrganism;
import il.ac.tau.arielgue.outxing.agents.UniformOrganism;
import il.ac.tau.arielgue.outxing.utils.Params;
import proevolution.agents.Organism;
import proevolution.helpers.OrganismTransformation;
import repast.simphony.random.RandomHelper;

public class FAOTransformation implements OrganismTransformation {

	/**
	 * we use FAOTransformation in 2 ways: transform from AA uniform population
	 * to FAO, and transform from BB FAO population to AB/BA or to AA uniform
	 */

	@Override
	public Organism transform(Organism original) {
		Organism oTransformed = null;
		if (Params.getOrganismTransformationCode() > 2) {
			oTransformed = transformFAOBB2UNIAA(original);
		} else if (Params.getOrganismTransformationCode() <= 2) {
			oTransformed = transform2FAO(original);
		}
		return oTransformed;
	}

	private Organism transform2FAO(Organism original) {
		FAOOrganism transformed = null;
		if (original instanceof OutXingOrganism) {
			OutXingOrganism castOriginal = (OutXingOrganism) original;
			transformed = (FAOOrganism) FAOOrganism.create(castOriginal);
			transformed.setMale(castOriginal.isMale()); // sets the gender from
			// the random created to the original's
			if (Params.getOrganismTransformationCode() == 1) {
				transformed.setOutXingModifier(OutXingOrganism.HOMOZYGOT_BB);
			} else if (Params.getOrganismTransformationCode() == 2 || Params.getOrganismTransformationCode() == 0){
				if (RandomHelper.nextDouble() < 0.5) {
					transformed
							.setOutXingModifier(OutXingOrganism.HETEROZYGOT_AB);
				} else {
					transformed
							.setOutXingModifier(OutXingOrganism.HETEROZYGOT_BA);
				}
			}
		} else {
			throw new ClassCastException("Can't cast organism of type "
					+ original.getClass().getName() + " to type "
					+ OutXingOrganism.class.getName());
		}

		return transformed;
	}

	private Organism transformFAOBB2UNIAA(Organism original) {
		UniformOrganism transformed = null;
		if (original instanceof UniformOrganism) {
			transformed = (UniformOrganism) original;
		} else if (original instanceof OutXingOrganism) {
			OutXingOrganism castOriginal = (OutXingOrganism) original;
			transformed = (UniformOrganism) UniformOrganism
					.create(castOriginal);
			transformed.setMale(castOriginal.isMale()); // sets the gender from
			// the random created to the original's
			if (Params.getOrganismTransformationCode() == 3) {
				transformed.setOutXingModifier(OutXingOrganism.HOMOZYGOT_AA);
			}
		} else {
			throw new ClassCastException("Can't cast organism of type "
					+ original.getClass().getName() + " to type "
					+ OutXingOrganism.class.getName());
		}
		return transformed;
	}

	@Override
	public String getTargetName() {
		if (Params.getOrganismTransformationCode() > 2) {
			return "Uniform Outcrosser";
		} else {
			return "Fitness Associated Outcrosser";
		}
	}
}
